#include"ContactsServer.h"
#include"httplib.h"
#include"ContactException.h"
using namespace std;
const static std::string IP = "172.31.249.195";
const static u_int16_t PORT = 8123;

void ContactsServer::addContact()
{
    //cout<<"add"<<endl;  
    httplib::Client cli(IP.c_str(),PORT);//构建客户端
    //构建request请求
    add_req::AddContactRequest req;
    buildAddContactRequest(&req);
    //序列化
    string req_str;
    if(!req.SerializeToString(&req_str))
    {
        throw ContactExpection("AddContactRequest 序列化失败！！！");
    }
    //发起请求
    auto res = cli.Post("/contact/add",req_str,"application/protobuf");
    if(!res)
    {
        string err_desc;
        err_desc.append("/contacts/add 链接错误！错误信息:").append(httplib::to_string(res.error()));
        throw ContactExpection(err_desc);
    }
    //反序列化
    add_resp::AddContactResponse resp;
    bool parse = resp.ParseFromString(res->body);
    if(res->status!=200 && !parse)
    {
        string err_desc;
        err_desc.append("post '/contacts/add/' 失败: ").append(std::to_string(res->status))
                .append("(").append(res->reason).append(")");
        throw ContactExpection(err_desc);
    }
    else if(res->status!=200)
    {
        string err_desc;
         err_desc.append("post '/contacts/add/' 失败: ").append(std::to_string(res->status))
                .append("(").append(res->reason).append(")").append("错误原因:").append(resp.base_resp().error_desc());
        throw ContactExpection(err_desc);
    }
    else if(!resp.base_resp().success())
    {
        string err_desc;
         err_desc.append("post '/contacts/add/' 结果异常: ")
         .append("异常原因:").append(resp.base_resp().error_desc());
        throw ContactExpection(err_desc);
    }
    //正常返回
    cout<<"新增联系人成功,联系人id:"<<resp.uid()<<endl;
}
void ContactsServer::delContact()
{
    //cout<<"del"<<endl;
    httplib::Client cli(IP.c_str(),PORT);
    del_req::DelContactRequest req;
    cout<<"请输入删除联系人id:";
    std::string uid;
    getline(cin,uid);
    req.set_uid(uid);

    //序列化
    string req_str;
    if(!req.SerializeToString(&req_str))
    {
        throw ContactExpection("DelContactRequest序列化失败!!!");

    }
    //发起post请求
    auto res = cli.Post("/contacts/del",req_str,"appliocation.protobuf");
    if(!res)
    {
        std::string err_desc;
        err_desc.append("/contacts/del 链接错误！错误信息:").append(httplib::to_string(res.error()));
        throw ContactExpection(err_desc);
    }
    //反序列化
    del_resp::DelContactResponse resp;
    bool parse = resp.ParseFromString(res->body);

     if(res->status!=200 && !parse)
    {
        string err_desc;
        err_desc.append("post '/contacts/del/' 失败: ").append(std::to_string(res->status))
                .append("(").append(res->reason).append(")");
        throw ContactExpection(err_desc);
    }
    else if(res->status!=200)
    {
        string err_desc;
         err_desc.append("post '/contacts/del/' 失败: ").append(std::to_string(res->status))
                .append("(").append(res->reason).append(")").append("错误原因:").append(resp.base_resp().error_desc());
        throw ContactExpection(err_desc);
    }
    else if(!resp.base_resp().success())
    {
        string err_desc;
         err_desc.append("post '/contacts/del/' 结果异常: ")
         .append("异常原因:").append(resp.base_resp().error_desc());
        throw ContactExpection(err_desc);
    }
    cout<<"成功删除id为: "<<resp.uid()<<" 的联系人"<<endl;
}
void ContactsServer::findContacts()
{
    // cout<<"find"<<endl;
    httplib::Client cli(IP.c_str(),PORT);
    //发起get请求
    auto res = cli.Get("/contacts/find-all");
    if(!res)
    {
        std::string err_desc;
        err_desc.append("/contacts/find-all 链接错误!错误信息：").append(httplib::to_string(res.error()));
        throw ContactExpection(err_desc);
    }

    //反序列化
    find_all_resp::FindAllResponse resp;
    bool parse = resp.ParseFromString(res->body);

    //异常处理
    if(res->status!=200 && !parse)
    {
        string err_desc;
        err_desc.append("get '/contacts/find-all/' 失败: ").append(std::to_string(res->status))
                .append("(").append(res->reason).append(")");
        throw ContactExpection(err_desc);
    }
    else if(res->status!=200)
    {
        string err_desc;
         err_desc.append("get '/contacts/find-all/' 失败: ").append(std::to_string(res->status))
                .append("(").append(res->reason).append(")").append("错误原因:").append(resp.base_resp().error_desc());
        throw ContactExpection(err_desc);
    }
    else if(!resp.base_resp().success())
    {
        string err_desc;
         err_desc.append("get '/contacts/find-all/' 结果异常: ")
         .append("异常原因:").append(resp.base_resp().error_desc());
        throw ContactExpection(err_desc);
    }
    printFindAllContactResponse(resp);

}
void ContactsServer::findOneContact()
{
    //cout<<"find 1"<<endl;
    httplib::Client cli(IP.c_str(),PORT);
    //构建请求
    find_one_req::FindOneRequest req;
    string uid;
    cout<<"请输入要查询的联系人id:";
    getline(cin,uid);
    req.set_uid(uid);

    //序列化
    string req_str;
    if(!req.SerializeToString(&req_str))
    {
        throw ContactExpection("FindOneRequest 序列化失败!!!");
    }
    //发起请求
    auto res = cli.Post("/contacts/find-one",req_str,"application/protobuf");
    if(!res)
    {
        std::string err_desc;
        err_desc.append("contacts/find-one 链接错误！错误信息: ").append(httplib::to_string(res.error()));
        throw ContactExpection(err_desc);
    }
    //反序列化 response
    find_one_resp::FindOneResponse resp;
    bool parse = resp.ParseFromString(res->body);
     if(res->status!=200 && !parse)
    {
        string err_desc;
        err_desc.append("post '/contacts/find-one/' 失败: ").append(std::to_string(res->status))
                .append("(").append(res->reason).append(")");
        throw ContactExpection(err_desc);
    }
    else if(res->status!=200)
    {
        string err_desc;
         err_desc.append("post '/contacts/find-one/' 失败: ").append(std::to_string(res->status))
                .append("(").append(res->reason).append(")").append("错误原因:").append(resp.base_resp().error_desc());
        throw ContactExpection(err_desc);
    }
    else if(!resp.base_resp().success())
    {
        string err_desc;
         err_desc.append("post '/contacts/find-one/' 结果异常: ")
         .append("异常原因:").append(resp.base_resp().error_desc());
        throw ContactExpection(err_desc);
    }
    cout<<"查询到联系人 id: "<<resp.uid()<<endl;
    printFindOneContactResponse(resp);
}
void ContactsServer::buildAddContactRequest(add_req::AddContactRequest* req)
{
    cout<<"请输入联系人姓名: ";
    string name;
    getline(cin,name);
    req->set_name(name);
    cout<<"请输入联系人年龄: ";
    int age;
    cin>>age;
    cin.ignore(256,'\n');
    req->set_age(age);
    for(int i=1;;i++)
    {
        cout<<"请输入联系人联系电话"<<i<<"(只输入回车完成新增): ";
        string number;
        getline(cin,number);
        if(number.empty())
        {
            break;
        }
        add_req::AddContactRequest_Phone* phone = req->add_phone();
        phone->set_number(number);
        cout<<"请选择新增电话类型:(1.移动电话 2.固定电话): ";
        int type;
        cin>>type;
        cin.ignore(256,'\n');
        switch(type)
        {
            case 1:
                phone->set_type(add_req::AddContactRequest_Phone_PhoneType::AddContactRequest_Phone_PhoneType_MP);
                break;
            case 2:
                  phone->set_type(add_req::AddContactRequest_Phone_PhoneType::AddContactRequest_Phone_PhoneType_TRL);
                break;
            default:
                cout<<"输入选项错误，使用默认值"<<endl;
                break;
        }
    }
    for(int i = 1;;i++)
    {
        cout<<"请输入备注信息"<<i<<"标题(只输入回车完成备注新增): ";
        std::string remark_key;
        getline(cin,remark_key);
        if(remark_key.empty())
        {
            break;
        }
        cout<<"请输入备注: "<<i<<"内容：";
        string remark_value;
        getline(cin,remark_value);
        req->mutable_remake()->insert({remark_key,remark_value});
    }
}
void ContactsServer::printFindOneContactResponse(find_one_resp::FindOneResponse& resp)
{
    cout<<"姓名: "<<resp.name()<<endl;
    cout<<"年龄: "<<resp.age()<<endl;
    int j=1;
    for(auto& phone:resp.phone())
    {
        cout<<"电话"<<j++<<": "<<phone.number();
        cout<<"("<<phone.PhoneType_Name(phone.type())<<")"<<endl;
    }
    if(resp.remake_size())
    {
        cout<<"备注信息:"<<endl;
        for(auto it = resp.remake().cbegin();it!=resp.remake().cend();it++)
        {
            cout<<"  "<<it->first<<": "<<it->second<<endl;
        }
    }
}
void ContactsServer::printFindAllContactResponse(find_all_resp::FindAllResponse& resp)
{
    if(0==resp.contacts_size())
    {
        cout<<"联系人列表为空，未添加任何联系人。"<<endl;
        return;
    }
    for(auto contact:resp.contacts())
    {
        cout<<"联系人姓名: "<<contact.name()<<" 联系人id: "<<contact.uid()<<endl;
    }
}